package com.iwhalecloud.citybrain.flow.platform.manager.application.service.impl;

import java.util.List;
import java.util.Objects;

import cn.hutool.core.util.StrUtil;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.AbstractEntityEventHandler;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.ProcessInstanceStartPostProcessor;
import com.iwhalecloud.citybrain.flow.platform.manager.common.ConstanceVariable;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.FlowProcessInstanceTraceVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.app.FlowApp;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowAppRepository;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowProcessInstanceTraceRepository;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.common.api.delegate.event.FlowableEngineEventType;
import org.flowable.engine.common.api.delegate.event.FlowableEventType;
import org.flowable.engine.common.impl.identity.Authentication;
import org.flowable.engine.delegate.event.impl.FlowableEntityEventImpl;
import org.flowable.engine.impl.persistence.deploy.DeploymentManager;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.repository.ProcessDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

/**
 * Handler - 流程实例启动完成事件处理
 *
 * @author lilh
 * @date 2019-01-28 16:02
 */
@Slf4j
@Component
public class ProcessInstanceStartedHandler extends AbstractEntityEventHandler {

    //@Autowired
    //private RuntimeService runtimeService;

    @Autowired
    private FlowProcessInstanceTraceRepository processInstanceTraceService;

    @Autowired
    private FlowAppRepository appService;

    @Lazy
    @Autowired(required = false)
    private List<ProcessInstanceStartPostProcessor> processors;

    @Override
    public FlowableEventType getEventType() {
        return FlowableEngineEventType.PROCESS_STARTED;
    }

    @Override
    protected void doHandle(FlowableEntityEventImpl event) {
        ExecutionEntity executionEntity = (ExecutionEntityImpl) event.getEntity();
        //添加整个流程实例级别的常用变量
        appendGlobalVariableToProcessInstance(executionEntity);
        if (Objects.nonNull(executionEntity.getVariable("isFromSdkCall"))) {
            processInstanceTraceService.updateLinkStatusToRunning(executionEntity.getProcessInstanceId());
        }
        executeCustomProcessor(executionEntity);
    }

    private void executeCustomProcessor(ExecutionEntity executionEntity) {
        for (ProcessInstanceStartPostProcessor processor : processors) {
            try {
                processor.process(executionEntity);
            } catch (Exception e) {
                log.warn("流程启动后执行自定义操作异常：{}", e.getMessage());
            }
        }
    }

    private void appendGlobalVariableToProcessInstance(ExecutionEntity executionEntity) {
        FlowProcessInstanceTraceVo ps = processInstanceTraceService.getProcessInstanceTraceByProcessInstanceId(executionEntity.getProcessInstanceId());
        executionEntity.setVariable(ConstanceVariable.MODEL_KEY, ps.getModelKey());
        executionEntity.setVariable(ConstanceVariable.PROCESS_DEFINITION_ID, ps.getProcessDefinitionId());
        executionEntity.setVariable(ConstanceVariable.MODEL_NAME, ps.getModelName());
        executionEntity.setVariable(ConstanceVariable.PROCESS_INSTANCE_ID, ps.getProcessInstanceId());
        executionEntity.setVariable(ConstanceVariable.APPLY_USER_ID, ps.getStarterId());
        executionEntity.setVariable(ConstanceVariable.APPLY_USER_NAME, ps.getStarterName());
        executionEntity.setVariable(ConstanceVariable.APPLY_TIME_STAMP, executionEntity.getStartTime().getTime());
        FlowApp app = appService.detail(ps.getAppId());
        if (Objects.nonNull(app)) {
            executionEntity.setVariable(ConstanceVariable.APP_CODE, app.getAppCode());
            executionEntity.setVariable(ConstanceVariable.APP_NAME, app.getAppName());
        } else {
            log.warn("应用[{} - {}]对应的数据不存在了", ps.getAppId(), ps.getAppName());
        }

        DeploymentManager deploymentCache = CommandContextUtil.getProcessEngineConfiguration().getDeploymentManager();
        ProcessDefinition processDefinition = deploymentCache.findDeployedProcessDefinitionById(ps.getProcessDefinitionId());
        if (Objects.nonNull(processDefinition)) {
            executionEntity.setVariable(ConstanceVariable.DEPLOYMENT_ID, processDefinition.getDeploymentId());
        }

        if (StrUtil.isBlank(Authentication.getAuthenticatedUserId())) {
            Authentication.setAuthenticatedUserId(ps.getStarterId());
        }

    }
}
